`timescale 1ns/1ns
`define DATA_WIDTH 256

module ZADDU_coz(input clk,
				 input rst_n,
				 input enable,
				 input MM_end_flag,
				 output reg MM_enable,
				 output reg func,
				 output reg [21:0] r_sel,
				 output reg [7:0] M_sel_a,
				 output reg [7:0] M_sel_b,
				 output reg [7:0] A_sel_a,
				 output reg [7:0] A_sel_b,
				 output reg end_flag
				);
				
reg [12:0] state,next_state;

parameter IDLE   =13'b0_0000_0000_0001,
           STEP1 =13'b0_0000_0000_0010,
		   STEP2 =13'b0_0000_0000_0100,
		   STEP3 =13'b0_0000_0000_1000,
		   STEP4 =13'b0_0000_0001_0000,
		   STEP5 =13'b0_0000_0010_0000,
		   STEP6 =13'b0_0000_0100_0000,
		   STEP7 =13'b0_0000_1000_0000,
		   STEP8 =13'b0_0001_0000_0000,
		   STEP9 =13'b0_0010_0000_0000,
		   STEP10=13'b0_0100_0000_0000,
		   STEP11=13'b0_1000_0000_0000,
		   STEP12=13'b1_0000_0000_0000;
		  
always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		state <= IDLE;
	end
	else
	begin
		state <= next_state;
	end
end

always @(*)
begin
	case(state)
	IDLE   :
			begin
				if((enable) & (!end_flag))
					next_state = STEP1;
				else
					next_state = IDLE;
			end
	STEP1  :
			begin
					next_state = STEP2;

			end
	STEP2  :
			begin
				if(MM_end_flag)
					next_state = STEP3;
				else
					next_state = STEP2;
			end
	STEP3  :
			begin
				if(MM_end_flag)
					next_state = STEP4;
				else
					next_state = STEP3;
			end
	STEP4  :
			begin
				if(MM_end_flag)
					next_state = STEP5;
				else
					next_state = STEP4;
			end	
	STEP5  :
		 	begin
				if(MM_end_flag)
					next_state = STEP6;
				else
					next_state = STEP5;
			end	
	STEP6  :
		 	begin
					next_state = STEP7;
			end	
	STEP7  :
			begin
					next_state = STEP8;
			end		
	STEP8  :
			begin
					next_state = STEP9;
			end	
	STEP9  :
			begin
				if(MM_end_flag)
					next_state = STEP10;
				else
					next_state = STEP9;
			end	
	STEP10 :
			begin
					next_state = STEP11;
			end	
	STEP11 :
			begin
				if(MM_end_flag)
					next_state = STEP12;
				else
					next_state = STEP11;
			end	
	STEP12 :
			begin
				next_state = IDLE;
			end
	default:
			begin
					next_state = IDLE;
			end
	endcase
end

always @(*)
begin
		case(state)
		/*
		IDLE:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		*/
		STEP1:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_1_0;
				A_sel_b = 8'b0_0_0_1_0_0_0_0;
			end
		STEP2:
			begin
				M_sel_a = 8'b0_1_0_0_0_0_0_0;
				M_sel_b = 8'b0_1_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_1_0_0;
				A_sel_b = 8'b0_0_1_0_0_0_0_0;
			end
		STEP3:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_1_0;
				M_sel_b = 8'b0_1_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP4:
			begin
				M_sel_a = 8'b0_1_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_1_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP5:
			begin
				M_sel_a = 8'b0_0_1_0_0_0_0_0;
				M_sel_b = 8'b0_0_1_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP6:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_1_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_1_0;
			end
		STEP7:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_1_0_0_0_0;
				A_sel_b = 8'b0_1_0_0_0_0_0_0;
			end
		STEP8:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_1_0;
				A_sel_b = 8'b0_1_0_0_0_0_0_0;
			end
		STEP9:
			begin
				M_sel_a = 8'b0_0_0_0_0_1_0_0;
				M_sel_b = 8'b0_1_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP10:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_1_0;
				A_sel_b = 8'b0_0_0_1_0_0_0_0;
			end
		STEP11:
			begin
				M_sel_a = 8'b0_0_1_0_0_0_0_0;
				M_sel_b = 8'b0_1_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP12:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_1_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_1_0_0;
			end
		default:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		endcase
end

always @(*)
begin
		case(state)
		/*
		IDLE  : 
			 	r_sel = 22'b0;
		*/
		STEP1 :
				r_sel = 22'b000_01_000_000_000_000_000_00;
		STEP2 :
				if(MM_end_flag)
				r_sel = 22'b000_10_001_000_000_000_000_00;
				else
				r_sel = 22'b000_10_000_000_000_000_000_00;
		STEP3 :
				r_sel = 22'b000_00_000_000_000_000_010_00;
		STEP4 :
				r_sel = 22'b000_10_000_000_000_000_000_00;
		STEP5 :
			 	r_sel = 22'b000_00_000_010_000_000_000_00;
		STEP6 :
				r_sel = 22'b000_00_000_001_000_000_000_00;
		STEP7 :
				r_sel = 22'b000_00_000_001_000_000_000_00;
		STEP8 :
				r_sel = 22'b000_01_000_000_000_000_000_00;
		STEP9 :
				r_sel = 22'b000_00_000_000_000_010_000_00;
		STEP10:
				r_sel = 22'b000_01_000_000_000_000_000_00;
		STEP11:
				r_sel = 22'b000_00_010_000_000_000_000_00;
		STEP12:
				r_sel = 22'b000_00_001_000_000_000_000_00;
		default:
				r_sel = 22'b0;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		MM_enable <= 1'b0;
	end
	else
	begin
		case(next_state)
		IDLE  :
					MM_enable <= 1'b0;
		STEP1 :
					MM_enable <= 1'b0;
		STEP2 :
				if(state == STEP1)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP3 :
				if(state == STEP2)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP4 :
				if(state == STEP3)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP5 :
				if(state == STEP4)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP6 :
					MM_enable <= 1'b0;
		STEP7 :
					MM_enable <= 1'b0;
		STEP8 :
					MM_enable <= 1'b0;
		STEP9 :
				if(state == STEP8)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP10:
					MM_enable <= 1'b0;
		STEP11:
				if(state == STEP10)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP12:
					MM_enable <= 1'b0;
		default:
					MM_enable <= 1'b0;
		endcase
	end
end

always @(*)
begin
		case(state)
		/*
		IDLE  :
					func = 1'b0;
		*/
		STEP1 :
					func = 1'b1;
		STEP2 :
					func = 1'b1;
		/*
		STEP3 :
					func = 1'b0;
		STEP4 :
					func = 1'b0;
		STEP5 :
					func = 1'b0;	
		*/
		STEP6 :	
					func = 1'b1;
		STEP7 :
					func = 1'b1;
		STEP8 :
					func = 1'b1;
		/*
		STEP9 :
					func = 1'b0;
		*/
		STEP10:
					func = 1'b1;	
		/*				
		STEP11:
					func = 1'b0;
		*/
		STEP12:
					func = 1'b1;	
		default:
					func = 1'b0;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		end_flag <= 1'b0;
	end
	else if(state == STEP12)
	begin
		end_flag <= 1'b1;
	end
	else
	begin
		end_flag <= 1'b0;
	end
end

endmodule
